
`include "alu_defs.v"

`timescale 1ns / 1ps

module tb_alu_top;

parameter CLK_PERIOD = 10;
parameter DATA_WIDTH = 32;

reg clk;
reg	i_reg_file_left;
reg	i_reg_file_right;
reg	i_q_reg_left;
reg	i_q_reg_right;
reg	i_cin;
reg	[8:0] i_instr;
reg	[4:0] i_a_addr;
reg	[4:0] i_b_addr;
reg	[DATA_WIDTH-1:0] i_data;

wire o_cout;
wire o_sign;
wire o_zero;
wire o_ovf;
wire o_reg_file_left;
wire o_reg_file_right;
wire o_q_reg_left;
wire o_q_reg_right;

wire [DATA_WIDTH-1:0] o_data;

defparam alu_top_DUT.DATA_WIDTH=DATA_WIDTH;

alu_top alu_top_DUT(
	.clk,
	.i_reg_file_left(i_reg_file_left),
	.i_reg_file_right(i_reg_file_right),
	.i_q_reg_left(i_q_reg_left),
	.i_q_reg_right(i_q_reg_right),
	.i_cin(i_cin),
	.i_instr(i_instr),
	.i_a_addr(i_a_addr),
	.i_b_addr(i_b_addr),
	.i_data(i_data),

	.o_cout(o_cout),
	.o_sign(o_sign),
	.o_zero(o_zero),
	.o_ovf(o_ovf),
	.o_reg_file_left(o_reg_file_left),
	.o_reg_file_right(o_reg_file_right),
	.o_q_reg_left(o_q_reg_left),
	.o_q_reg_right(o_q_reg_right),
	.o_data(o_data)
);

initial
begin
	set_all_inputs_to_inactive_and_default;
	#10
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 0, 0 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 1, 1 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 2, 2 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 3, 3 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 4, 4 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 5, 5 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 6, 6 );
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMA, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 7, 7 );
	
	set_instr_and_ops_and_clk( { `ALU_MNEM_QREG, `ALU_FUNC_ADD, `ALU_OP_DZ }, 0, 8, 2 );
		
	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMD, `ALU_FUNC_ADD, `ALU_OP_DA }, 0, 8, 2 );

	set_instr_and_ops_and_clk( { `ALU_MNEM_RAMU, `ALU_FUNC_ADD, `ALU_OP_DA }, 0, 9, 2 );
				
	#10
	$finish;
end

always
	#(CLK_PERIOD/2) clk = ~clk;

task set_all_inputs_to_inactive_and_default;
begin
	clk = 0;
	i_reg_file_left = 0;
	i_reg_file_right = 0;
	i_q_reg_left = 0;
	i_q_reg_right = 0;
	i_cin = 0;
	i_instr = `ALU_MNEM_NOP;
	i_a_addr = 0;
	i_b_addr = 0;
	i_data = 0;
end
endtask

task set_instr_and_ops;
	input [8:0] instr;
	input [4:0] a_addr;
	input [4:0] b_addr;
	input [DATA_WIDTH-1:0] data;
begin
	i_instr = instr;
	i_a_addr = a_addr;
	i_b_addr = b_addr;
	i_data = data;
end
endtask

task set_instr_and_ops_and_clk;
	input [8:0] instr;
	input [4:0] a_addr;
	input [4:0] b_addr;
	input [DATA_WIDTH-1:0] data;
begin
	set_instr_and_ops( instr, a_addr, b_addr, data);
	#10
	;
end
endtask

endmodule
